# MusicScreen - This screen allows user to select music he/she wants to listen
# Copyright (C) 2007 Lauri Taimila
# 
# Entertainer is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Entertainer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2007, Lauri Taimila"
__author__ = "Lauri Taimila <lauri@taimila.com>"

import os
import gtk
import time
import pango
import gobject
import clutter

from frontend.gui.screens.screen import Screen
from frontend.gui.transitions.transition import Transition

# Widgets
from frontend.gui.widgets.tabs_menu import TabsMenu
from frontend.gui.widgets.text_menu import TextMenu
from frontend.gui.widgets.image_menu import ImageMenu

from frontend.gui.widgets.text_menu_item import TextMenuItem
from frontend.gui.widgets.image_menu_item import ImageMenuItem
from frontend.gui.widgets.justified_text_menu_item import JustifiedTextMenuItem

from frontend.gui.widgets.list_indicator import ListIndicator

# Music library
from frontend.medialibrary.music import MusicLibrary
from frontend.medialibrary.music import Track
from frontend.medialibrary.music import Album

class MusicScreen(Screen):
    """
    MusicScreen
    
    Screen that allows user to browse music library content.
    """
    
    def __init__(self, ui, frontend):
        """
        Initialize screen
        
        @param frontend: FrontendClient object
        @param theme: Theme object
        """
        self.ui = ui
        self.frontend = frontend
        self.theme = frontend.getTheme()
        self.library = self.frontend.get_music_library()
        self.group = clutter.Group()
        
        # Screen Title (Displayed at the bottom left corner)
        screen_title = clutter.Label()
        screen_title.set_font_name(self.theme.getFont() + ' 100px')
        screen_title.set_color(self.theme.getColor("screentitle"))
        screen_title.set_text("Music")
        screen_title.set_name("screen_title")
        (screen_title_width, screen_title_height) = screen_title.get_size()
        screen_title_x = 0
        screen_title_y = ui.STAGE_HEIGHT - screen_title_height + 20
        screen_title.set_position(screen_title_x, screen_title_y)
        screen_title.show()
        self.group.add(screen_title)
        
        # Create tabs and content
        self._create_albums_tab()
        self._create_artists_tab()
        self._create_playlists_tab()
        self._create_genres_tab()
        self._create_tabs()
        
        self.current_tab = "artists"
        self.artists_tab.show()
        
        self.group.show()
        ui.getStage().add(self.group)
    
    def _create_tabs(self):
        """
        Create tab bar of the screen. Tabs: Movies, TV-Series, Video clips
        """
        self.tabs = TabsMenu(self.theme, 
                        self.frontend.get_configuration().show_effects())
        self.tabs.set_item_size(300, 60)
        self.tabs.set_visible_column_count(4)
        
        tab1 = JustifiedTextMenuItem(300, 60, self.theme, "Artists", JustifiedTextMenuItem.CENTER)
        tab1.set_userdata("artists")
        self.tabs.add_actor(tab1)
        
        tab2 = JustifiedTextMenuItem(300, 60, self.theme, "Albums", JustifiedTextMenuItem.CENTER)
        tab2.set_userdata("albums")
        self.tabs.add_actor(tab2)
        
        tab3 = JustifiedTextMenuItem(300, 60, self.theme, "Playlists", JustifiedTextMenuItem.CENTER)
        tab3.set_userdata("playlists")
        self.tabs.add_actor(tab3)
        
        tab4 = JustifiedTextMenuItem(300, 60, self.theme, "Genres", JustifiedTextMenuItem.CENTER)
        tab4.set_userdata("genres")
        self.tabs.add_actor(tab4)
        
        self.tabs.set_position(83, 40)
        self.tabs.set_active(True)
        self.tabs.show()
        self.group.add(self.tabs)
    
    def _create_artists_tab(self):
        """
        Create a list of artists
        """
        self.artists_tab = clutter.Group()
        self.artist_menu = TextMenu(self.theme, 
                               self.frontend.get_configuration().show_effects())
        self.artist_menu.set_item_size(400, 60)
        cursor = clutter.Rectangle()
        cursor.set_color((0,0,0,0))
        self.artist_menu.set_cursor(cursor)
        
        artists = self.library.get_all_artists()
        
        #def async_menu_build():
        for artist in artists:
            item = JustifiedTextMenuItem(400, 60, self.theme, artist)
            item.set_userdata(artist)
            self.artist_menu.add_actor(item)
            #time.sleep(0.01)
        #    self.artist_li.set_maximum(self.artist_menu.get_number_of_items())
        #    return False
        #gobject.timeout_add(0, async_menu_build)
        
        self.artist_menu.set_orientation(TextMenu.HORIZONTAL)
        self.artist_menu.set_row_count(7)
        self.artist_menu.set_visible_column_count(3)
        
        self.artist_menu.set_position(80,160)
        self.artist_menu.set_active(False)
        self.artist_menu.show()
        
        if self.frontend.get_configuration().show_effects():
            self.artist_menu.set_animate(True)
        
        self.artists_tab.add(self.artist_menu)
        
        # Create artist label
        self.artist_title = clutter.Label()
        self.artist_title.set_text(" ")
        self.artist_title.set_font_name(self.theme.getFont() + ' 32px')
        self.artist_title.set_color(self.theme.getColor("title"))
        self.artist_title.set_line_wrap(False)
        #self.artist_title.set_ellipsize(pango.ELLIPSIZE_END)
        self.artist_title.set_position(300, 610)
        self.artist_title.set_size(500,40)
        self.artist_title.show()
        self.artists_tab.add(self.artist_title)
        
        self.artist_albums = clutter.Label()
        self.artist_albums.set_text(" ")
        self.artist_albums.set_font_name(self.theme.getFont() + ' 28px')
        self.artist_albums.set_color(self.theme.getColor("subtitle"))
        self.artist_albums.set_line_wrap(False)
        #self.artist_albums.set_ellipsize(pango.ELLIPSIZE_END)
        self.artist_albums.set_position(300, 660)
        self.artist_albums.set_size(500,40)
        self.artist_albums.show()
        self.artists_tab.add(self.artist_albums)
        
        self.artist_tracks = clutter.Label()
        self.artist_tracks.set_text(" ")
        self.artist_tracks.set_font_name(self.theme.getFont() + ' 28px')
        self.artist_tracks.set_color(self.theme.getColor("subtitle"))
        self.artist_tracks.set_position(300, 700)
        self.artist_tracks.set_size(500,40)
        self.artist_tracks.set_line_wrap(False)
        #self.artist_tracks.set_ellipsize(pango.ELLIPSIZE_END)
        self.artist_tracks.show()
        self.artists_tab.add(self.artist_tracks)
        
        # Create artis menu list indicator
        self.artist_li = ListIndicator(200, 34, self.theme, ListIndicator.HORIZONTAL)
        self.artist_li.set_position(1270 - self.album_li.get_width(), 610)
        self.artist_li.set_delimiter(" | ")
        self.artist_li.set_maximum(self.artist_menu.get_number_of_items())
        self.artist_li.set_current(1)
        self.artist_li.show()
        self.artists_tab.add(self.artist_li)
        
        self.group.add(self.artists_tab)
        
    def _create_albums_tab(self):
        """
        Create a list of albums
        """
        self.albums_tab = clutter.Group()
        
        # Create albums menu
        self.album_menu = ImageMenu(self.theme)
        self.album_menu.set_item_size(150, 150)
        albums = self.library.get_all_albums()
        
        # Default texture
        default_cover = clutter.Texture()
        buffer = gtk.gdk.pixbuf_new_from_file(self.theme.getImage("default_album_art"))
        default_cover.set_pixbuf(buffer)
        
        def async_menu_build():
            for album in albums:
                if album.has_album_art():
                    texture = clutter.Texture()
                    buffer = gtk.gdk.pixbuf_new_from_file(album.get_album_art_url())
                    texture.set_pixbuf(buffer)
                else:
                    texture = clutter.CloneTexture(default_cover)
                
                item = ImageMenuItem(150, 150, texture)
                item.set_userdata(album)
                self.album_menu.add_actor(item)
                time.sleep(0.01)
            self.album_li.set_maximum(self.album_menu.get_number_of_items())
            return False
        gobject.timeout_add(0, async_menu_build)

        self.album_menu.set_position(80,140)
        self.album_menu.set_active(False)
        self.album_menu.show()
        
        if self.frontend.get_configuration().show_effects():
            self.album_menu.set_animate(True)
        
        self.albums_tab.add(self.album_menu)
        
        # Create album menu list indicator
        self.album_li = ListIndicator(200,34, self.theme, ListIndicator.HORIZONTAL)
        self.album_li.set_position(1270 - self.album_li.get_width(), 610)
        self.album_li.set_delimiter(" | ")
        self.album_li.set_maximum(self.album_menu.get_number_of_items())
        self.album_li.set_current(1)
        self.album_li.show()
        self.albums_tab.add(self.album_li)
        
        # Create album information (displays current menuitem information)
        self.album_title = clutter.Label()
        self.album_title.set_text(" ")
        self.album_title.set_font_name(self.theme.getFont() + ' 32px')
        self.album_title.set_color(self.theme.getColor("title"))
        self.album_title.set_line_wrap(False)
        #self.album_title.set_ellipsize(pango.ELLIPSIZE_END)
        self.album_title.set_position(300, 610)
        self.album_title.set_size(500,40)
        self.album_title.show()
        self.albums_tab.add(self.album_title)
        
        self.album_artist = clutter.Label()
        self.album_artist.set_text(" ")
        self.album_artist.set_font_name(self.theme.getFont() + ' 28px')
        self.album_artist.set_color(self.theme.getColor("subtitle"))
        self.album_artist.set_line_wrap(False)
        #self.album_artist.set_ellipsize(pango.ELLIPSIZE_END)
        self.album_artist.set_position(300, 660)
        self.album_artist.set_size(500,40)
        self.album_artist.show()
        self.albums_tab.add(self.album_artist)
        
        self.album_tracks = clutter.Label()
        self.album_tracks.set_text(" ")
        self.album_tracks.set_font_name(self.theme.getFont() + ' 28px')
        self.album_tracks.set_color(self.theme.getColor("subtitle"))
        self.album_tracks.set_position(300, 700)
        self.album_tracks.set_size(500,40)
        self.album_tracks.set_line_wrap(False)
        #self.album_tracks.set_ellipsize(pango.ELLIPSIZE_END)
        self.album_tracks.show()
        self.albums_tab.add(self.album_tracks)
        
        self.group.add(self.albums_tab)
        
    def _create_playlists_tab(self):
        """
        Create a list of playlists
        """
        playlists = self.library.get_playlists()
        self.playlists_tab = clutter.Group()
        
        if len(playlists) == 0:
            empty_label = clutter.Label()
            empty_label.set_text("No saved playlists available.")
            empty_label.set_font_name(self.theme.getFont() + ' 38px')
            empty_label.set_color(self.theme.getColor("title"))
            x = (self.ui.STAGE_WIDTH / 2) - (empty_label.get_width() / 2)
            y = (self.ui.STAGE_HEIGHT / 2) - (empty_label.get_height() / 2)
            empty_label.set_position(x,y)
            empty_label.show()
            self.playlists_tab.add(empty_label)
        else:   
            self.playlist_menu = TextMenu(self.theme, 
                                   self.frontend.get_configuration().show_effects())
            self.playlist_menu.set_item_size(700, 60)
            
            for playlist in playlists:
                item = TextMenuItem(700, 60, self.theme, playlist)
                item.set_userdata(playlist)
                self.playlist_menu.add_actor(item)
            
            self.playlist_menu.set_position(550,140)
            #self.playlist_menu.set_active(False)
            self.playlist_menu.show()
            
            if self.frontend.get_configuration().show_effects():
                self.playlist_menu.set_animate(True)
            
            self.playlists_tab.add(self.playlist_menu)
            
        self.group.add(self.playlists_tab)
        
    def _create_genres_tab(self):
        """
        Create a list of genres
        """
        self.genres_tab = clutter.Group()
        #FIXME: Implement it!
        self.group.add(self.genres_tab)
    
    def _update_album_info(self, album):
        """
        Update album information. This information is displayed on albums tab.
        @param album: Album object
        """
        self.album_title.set_text(album.get_title())
        self.album_artist.set_text(album.get_artist())
        self.album_tracks.set_text(str(album.get_number_of_tracks()) + " tracks")
       
    def _update_artist_info(self, artist):
        """
        Update artist information. This information is displayed on artist tab.
        @param artist: Artist name
        """
        self.artist_title.set_text(artist)
        self.artist_albums.set_text(str(self.library.number_of_albums_by_artist(artist)) + " albums")
        self.artist_tracks.set_text(str(self.library.number_of_tracks_by_artist(artist)) + " tracks")
       
    def _change_tab(self):
        """
        Change tab. This is called when user changes the screen tab.
        """
        self.artists_tab.hide()
        self.albums_tab.hide()
        self.playlists_tab.hide()
        self.genres_tab.hide()
            
        self.current_tab = self.tabs.get_current_menuitem().get_userdata()
        if self.current_tab == "artists":
            self.artists_tab.show()
        elif self.current_tab == "albums":
            self.albums_tab.show()
        elif self.current_tab == "playlists":
            self.playlists_tab.show()
        elif self.current_tab == "genres":
            self.genres_tab.show()
        
    def get_group(self):
        """
        Get all actors of the screen.
        @return clutter.Group 
        """
        return self.group

    def get_type(self):
        """Return screen type."""
        return Screen.NORMAL
    
    def get_name(self):
        """Return screen name (human readble)"""
        return "MusicScreen"
    
    def handle_key_press_event(self, event):   
        """ Handle key pressed event."""
        #UP KEY
        if event.keyval == clutter.keysyms.Up:
            if self.current_tab == "artists":
                if self.artist_menu.get_cursor_position()[1] == 0:
                    self.artist_menu.set_active(False)
                    self.tabs.set_active(True)
                else:
                    self.artist_menu.move(self.album_menu.UP)
                    self._update_artist_info(self.artist_menu.get_current_menuitem().get_userdata())
                    self.artist_li.set_current(self.artist_menu.get_current_postition() + 1)
            
            elif self.current_tab == "albums":
                if self.album_menu.get_cursor_position()[1] == 0:
                    self.album_menu.set_active(False)
                    self.tabs.set_active(True)
                else:
                    self.album_menu.move(self.album_menu.UP)
                    self._update_album_info(self.album_menu.get_current_menuitem().get_userdata())
                    self.album_li.set_current(self.album_menu.get_current_postition() + 1)
                    
            elif self.current_tab == "playlists":
                pass
            elif self.current_tab == "genres":
                pass
        
        #DOWN KEY  
        elif event.keyval == clutter.keysyms.Down:
            # Activate tab menu if tab bar was active
            if self.tabs.is_active():
                self.tabs.set_active(False)
                if self.current_tab == "artists":
                    self.artist_menu.set_active(True)
                    self._update_artist_info(self.artist_menu.get_current_menuitem().get_userdata())
                elif self.current_tab == "albums":
                    self.album_menu.set_active(True)
                    self._update_album_info(self.album_menu.get_current_menuitem().get_userdata())
                elif self.current_tab == "playlists":
                    self.playlist_menu.set_active(True)
                elif self.current_tab == "genres":
                    self.genre_menu.set_active(True)
                return
            
            if self.current_tab == "artists":
                self.artist_menu.move(self.artist_menu.DOWN)
                self._update_artist_info(self.artist_menu.get_current_menuitem().get_userdata())
                self.artist_li.set_current(self.artist_menu.get_current_postition() + 1)
            elif self.current_tab == "albums":
                self.album_menu.move(self.album_menu.DOWN)
                self._update_album_info(self.album_menu.get_current_menuitem().get_userdata())
                self.album_li.set_current(self.album_menu.get_current_postition() + 1)
            elif self.current_tab == "playlists":
                pass
            elif self.current_tab == "genres":
                pass
        
        #LEFT KEY
        elif event.keyval == clutter.keysyms.Left:
            if self.tabs.is_active():
                self.tabs.move(self.tabs.LEFT)
                self._change_tab()  
            elif self.current_tab == "artists":
                self.artist_menu.move(self.artist_menu.LEFT)
                self._update_artist_info(self.artist_menu.get_current_menuitem().get_userdata())
                self.artist_li.set_current(self.artist_menu.get_current_postition() + 1)
            elif self.current_tab == "albums":
                self.album_menu.move(self.album_menu.LEFT)
                self._update_album_info(self.album_menu.get_current_menuitem().get_userdata())
                self.album_li.set_current(self.album_menu.get_current_postition() + 1)
            elif self.current_tab == "playlists":
                pass
            elif self.current_tab == "genres":
                pass
        
        # RIGHT KEY
        elif event.keyval == clutter.keysyms.Right:
            if self.tabs.is_active():
                self.tabs.move(self.tabs.RIGHT)
                self._change_tab()  
            elif self.current_tab == "artists":
                self.artist_menu.move(self.artist_menu.RIGHT)
                self._update_artist_info(self.artist_menu.get_current_menuitem().get_userdata())
                self.artist_li.set_current(self.artist_menu.get_current_postition() + 1)
            elif self.current_tab == "albums":
                self.album_menu.move(self.album_menu.RIGHT)
                self._update_album_info(self.album_menu.get_current_menuitem().get_userdata())
                self.album_li.set_current(self.album_menu.get_current_postition() + 1)
            elif self.current_tab == "playlists":
                pass
            elif self.current_tab == "genres":
                pass
        
        # RETURN KEY
        elif event.keyval == clutter.keysyms.Return:
            if self.current_tab == "artists": 
                artist = self.artist_menu.get_current_menuitem().get_userdata()
                self.ui.changeScreen(self.ui.createScreen("artist", artist), Transition.FORWARD)
            elif self.current_tab == "albums":
                album = self.album_menu.get_current_menuitem().get_userdata()
                self.ui.changeScreen(self.ui.createScreen("music_album", album), Transition.FORWARD)
            elif self.current_tab == "playlists":
                pass
            elif self.current_tab == "genres":
                pass
